// 生产者和消费者模型测试

// 中间交易场所用 : 阻塞队列实现

// 先测试 : 单生产者和单消费者

#include <pthread.h>
#include "BlockQueue.hpp"
#include <string>
#include <iostream>
#include <unistd.h>
#include "Task.hpp"

using namespace BlockQueueModel;

// 生产者
void *productor(void *args)
{
    // 阻塞队列
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);

    while (true)
    {
        int x = 1;
        int y = 1;
        BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
        while (true)
        {
            // sleep(1);
            std::cout << "生产了一个任务: " << x << "+" << y << "=?" << std::endl;
            Task t(x, y);
            bq->EnterQueue(t);

            x++, y++;
        }
    }
}
void *consumer(void *args)
{
    // 阻塞队列
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    while (true)
    {
        sleep(1); // 消费快一点
        std::cout << " 我消费了一个任务 ! " << std::endl;
        Task t = bq->PopQueue();
        // 处理任务
        t.Execute();

        std::cout << "消费了一个任务: " << t.X() << "+" << t.Y() << "=" << t.Result() << std::endl;
    }
}

int main()
{

    // 申请阻塞队列 , new 个对象
    // BlockQueue<int> *bq = new BlockQueue<int>();
    BlockQueue<Task> *bq = new BlockQueue<Task>();

    // /////// 1. 单生产者和单消费者
    // // 创建生产者和消费者
    // pthread_t p, c;
    // pthread_create(&p, nullptr, productor, bq);

    // pthread_create(&c, nullptr, consumer, bq);

    // // 主线程等待两个线程
    // pthread_join(p, nullptr);

    // pthread_join(c, nullptr);

    // 多生产者和多消费者
    // 首先要满足 : 各自之间为互斥 , 生产和消费满足同步和互斥
    // 单生产者和单消费者的代码就是满足这样的关系 : 有锁 , 有条件变量实现同步
    // 所以代码不用改 !!

    // 两个生产者和三个消费者
    // 构建生产和消费者
    pthread_t c[2], p[3];

    //数组名就是数组首元素地址
    pthread_create(c, nullptr, consumer, bq);
    pthread_create(c+1, nullptr, consumer, bq);
    pthread_create(p, nullptr, productor, bq);
    pthread_create(p+1, nullptr, productor, bq);
    pthread_create(p+2, nullptr, productor, bq);

    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);
    return 0;
}